package com.oracle.outsidein.pool;

import lombok.extern.slf4j.Slf4j;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Slf4j
public class ConvertTaskWv extends AbstractConvertTask {

    public ConvertTaskWv(ConvertTaskInfo info) {
        super(info);
    }

    @Override
    public ConvertResult call() throws Exception {
        return super.call();
    }

    @Override
    public void convertBefore() {
        if (info.wv2zip || info.wv2mht) {
            String fd = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
            File tmp = new File(config.getWorkingDir(), fd);
            if (!tmp.mkdir()) {
                throw new RuntimeException("create dir " + tmp.getAbsolutePath() + " failed");
            }
            dst = new File(tmp, "index.html");
        }
        if (info.wv2zip) {
            info.dstFile += ".zip";
        } else if (info.wv2mht) {
            info.dstFile += ".mht";
        }
    }

    @Override
    public void convertAfter() {
        if (info.wv2zip) {
            packZip(dst, info.dstFile);
            deleteDir(dst.getParentFile());
        } else if (info.wv2mht) {
            packMht(dst, info.dstFile);
            deleteDir(dst.getParentFile());
        }
    }

    // 压缩mht
    private void packMht(File dst, String dstFile) {
        // TODO
    }

    // 压缩zip
    private void packZip(File dst, String dstFile) {
        File dir = dst.getParentFile();
        log.info("packZip dir={} zip={}", dir.getPath(), dstFile);
        try (FileOutputStream fos = new FileOutputStream(dstFile);
             ZipOutputStream zipOutputStream = new ZipOutputStream(fos)) {
            File assets = config.getWvAssets();
            for (File f : Objects.requireNonNull(assets.listFiles())) {
                compress(zipOutputStream, f, "");
            }
            for (File f : Objects.requireNonNull(dir.listFiles())) {
                compress(zipOutputStream, f, "");
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    private static void compress(ZipOutputStream out, File sourceFile, String base) throws Exception {
        if (sourceFile.isDirectory()) {
            File[] fs = sourceFile.listFiles();
            assert fs != null;
            if (fs.length == 0) {
                out.putNextEntry(new ZipEntry(base + File.separator));
            } else {
                for (File f : fs) {
                    compress(out, f, base + File.separator + f.getName());
                }
            }
        } else {
            log.debug("compress={}", sourceFile);
            out.putNextEntry(new ZipEntry(base + sourceFile.getName()));
            try (FileInputStream fos = new FileInputStream(sourceFile);
                 BufferedInputStream bis = new BufferedInputStream(fos)) {
                int len;
                byte[] buf = new byte[1024];
                while ((len = bis.read(buf)) != -1) {
                    out.write(buf, 0, len);
                }
            }
        }
    }
}
